﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using ProjectBase.Core;
using ProjectBase.Core.Service;
using ProjectBase.Core.Web;

namespace ProjectBase.Mvc.Controllers
{
    public class EntityBinder : SmartBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            IPersistentObject entity;

            if (TryInjectEntity(controllerContext, bindingContext, out entity))
            {
                return entity;
            }

            return base.BindModel(controllerContext, bindingContext);
        }


        #region Inject IPersistentObject
        protected virtual bool TryInjectEntity(ControllerContext controllerContext, ModelBindingContext bindingContext, out IPersistentObject entity)
        {
            var entityExists = BindExistingPersistentItem(bindingContext, out entity);

            if (entityExists && entity.Is())
            {
                BindEntity(entity, controllerContext, bindingContext.ValueProvider);
                return true;
            }
            return false;
        }

        protected virtual bool BindExistingPersistentItem(ModelBindingContext bindingContext, out IPersistentObject entity)
        {
            entity = null;
            var type = bindingContext.ModelType;

            var isModelPersistentObject = type.HasType(typeof(IPersistentObject))
                                        && bindingContext.Model.IsNull();

            if (isModelPersistentObject)
            {
                // id for GetById()
                var idValue = bindingContext.ValueProvider.GetValue(Constants.Common.ID);
                var actionName = bindingContext.ValueProvider.GetValue(Constants.Common.Action);

                // is it new action? CreateNew()
                var isNew = idValue.AttemptedValue.IsEmpty()
                         || actionName.AttemptedValue.IsEqual(Constants.Actions.New);

                var provider = ModelMetadataProviders.Current;
                if (isNew)
                {
                    bindingContext.ModelMetadata = provider.GetMetadataForType(
                        () => CreateIPersistentObject(type)
                        , bindingContext.ModelType);

                    entity = bindingContext.Model as IPersistentObject;
                    return true;
                }

                bindingContext.ModelMetadata = provider.GetMetadataForType(
                    () => FindIPersistentObjects(type, idValue).FirstOrDefault()
                    , bindingContext.ModelType);

                entity = bindingContext.Model as IPersistentObject;
                return true;
            }
            return false;
        }
        protected virtual bool BindEntity(IPersistentObject entity, ControllerContext controllerContext, IValueProvider valueProvider)
        {
            var controller = controllerContext.Controller as IHaveEntityBinder;
            if (controller.Is())
            {
                return controller.BindEntity(entity, valueProvider);
            }
            return false;
        }

        #endregion Inject IPersistentObject
    }
}